package com.xiaoge.service;

import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * TODO
 *
 *     @Bean
 *     @ConditionalOnBean(value = MemberService.class)
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *
 *     TODO @ConditionalOnBean(value = MemberService.class)  ioc容器中有MemberService类型单例对象, orderService才会被注入到ioc容器中
 *          @ConditionalOnBean(value = "bean类型")
 *          @ConditionalOnBean(name = "bean名称")
 *          @ConditionalOnBean 不写value/name默认是方法返回值类型
 *
 *
 *
 *     @Bean
 *     @ConditionalOnMissingBean(name = "userService")
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *     TODO @ConditionalOnMissingBean(value = UserService.class) ioc容器中没有UserService类型单例对象, orderService才会被注入到ioc容器中
 *          @ConditionalOnMissingBean(value = "bean类型")
 *          @ConditionalOnMissingBean(name = "bean名称")
 *          @ConditionalOnMissingBean 不写value/name默认是方法返回值类型
 *
 *
 *     @Bean
 *     @ConditionalOnSingleCandidate(value = UserService.class)
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *     TODO @ConditionalOnSingleCandidate(value = UserService.class) ioc容器中用UserService类型对象, 但是只能有一个, orderService才会被注入到ioc容器中
 *          @ConditionalOnSingleCandidate(value = "bean类型")
 *          @ConditionalOnSingleCandidate(name = "bean名称")
 *          @ConditionalOnSingleCandidate 不写value/name默认是方法返回值类型
 *          1. 使用该注解要对springBean加载顺序非常了解, 要不然, 装配了这个注解的bean明明有两个但是还是会被注入进去
 *          因为spring在扫描的时候, 扫描了其中一个UserService类型 bean, 另外一个UserService类型 bean还没有被扫描到
 *          就先扫描了当前orderService()方法, 所以它会被注入到ioc容器中
 *          2. 最好是使用自动装配, 把标注了该注解的方法仿造spring.factories文件中, 这样@ConditionalOnSingleCandidate百分百生效
 *          因为, 自动装配实现了DeferredImportSelector接口, 它是延迟的, 它会等项目中所有的bean加载完了, 再去加载spring.factories中的Bean
 *
 *
 *     @Bean
 *     @ConditionalOnClass(value = UserService.class)
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *     TODO @ConditionalOnClass(value = UserService.class) 当前classpath中有UserService类型的类, orderService才会被注入到ioc容器中
 *          @ConditionalOnClass(value = "class类型")
 *          @ConditionalOnClass(name = "class名称") 权限定类名 (@ConditionalOnClass(name = "com.xiaoge.service.UserService"))
 *
 *
 *     @Bean
 *     @ConditionalOnMissingClass(value = "com.xiaoge.service.UserService")
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *     TODO @ConditionalOnMissingClass(value = "com.xiaoge.service.UserService") 当前classpath中没有UserService类型的类, orderService才会被注入到ioc容器中
 *
 *
 *     @Bean
 *     @ConditionalOnExpression(value = "#{!'abc'.equals(environment.getProperty('test.condition'))}")
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *
 *     TODO @ConditionalOnExpression(value = "${test.condition} == true") ${test.condition} == true结果为 true, orderService才会被注入到ioc容器中
 *          @ConditionalOnExpression(value = "#{!'abc'.equals(environment.getProperty('test.condition'))}") 复杂表达式这样写#{}
 *
 *
 *     @Bean
 *     @ConditionalOnJava(value = JavaVersion.EIGHT)
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *
 *     TODO @ConditionalOnJava(value = JavaVersion.EIGHT)   当前系统jdk版本跟指定的java版本相同则为true, true的情况下, orderService才会被注入到ioc容器中
 *          @ConditionalOnJava(value = "java版本") 
 *          @ConditionalOnJava(range = "java版本范围", value = "java版本") 比较方式，Range.EQUAL_OR_NEWER:当前版本等于或高于、Range.OLDER_THAN:当前版本老于，越早的版本越老
 *
 *
 *     @Bean
 *     @ConditionalOnWebApplication
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *
 *     TODO @ConditionalOnWebApplication 当前应用是一个web应用, orderService才会被注入到ioc容器中
 *
 *
 *     @Bean
 *     @ConditionalOnNotWebApplication
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *
 *     TODO @ConditionalOnNotWebApplication 当前应用不是一个web应用, orderService才会被注入到ioc容器中
 *
 *
 *     @Bean
 *     @ConditionalOnProperty(name = "test.condition123", matchIfMissing = true) Environment中是否存在某个属性
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *
 *     TODO @ConditionalOnProperty(name = "test.condition") 当前properties文件中有test.condition属性, orderService才会被注入到ioc容器中
 *          @ConditionalOnProperty(name = "test.condition123", matchIfMissing = true) 当前properties文件中不管有没有test.condition123属性, orderService都会被注入到ioc容器中(因为matchIfMissing = true, 默认matchIfMissing = false)
 *
 *
 *     @Bean
 *     @ConditionalOnResource(resources = "http://www.baidu.com")
 *     public OrderService orderService() {
 *         return new OrderService();
 *     }
 *
 *     TODO @ConditionalOnResource(resources = "http://www.baidu.com") 指定一个资源, 当前资源存在(本地/网络), orderService才会被注入到ioc容器中
 *
 *
 *
 *     TODO @ConditionalOnWarDeployment：当前项⽬是不是以War包部署的⽅式运⾏
 *     TODO @ConditionalOnCloudPlatform：是不是在某个云平台上
 *
 *      @Bean
 *      @Profile(value = "dev")
 *      public OrderService orderService() {
 *         return new OrderService();
 *     }
 *     TODO @Profile(value = "dev") 当前环境是dev, , orderService才会被注入到ioc容器中
 *          spring.profiles.active: dev  自己在application.yml中配置对应版本@Profile->value的值必须跟spring.profiles.active值相同
 *          要不然bean不能被注入到ioc中
 *
 *
 * @author <a href="mailto:zhangxiao@dist.com.cn">Zhang Xiao</a>
 * @since
 */
@Configuration
public class AppConfig {

    @Bean
    @ConditionalOnResource(resources = "http://www.baidu.com")
    public OrderService orderService() {
        return new OrderService();
    }

}
